package com.sharefang.aproject.net;

import com.orhanobut.logger.Logger;
import com.sharefang.aproject.bean.BaseBean;
import com.sharefang.aproject.bean.NppBean;
import com.sharefang.aproject.bean.PptBean;
import com.sharefang.aproject.bean.UserBean;
import com.sharefang.aproject.utils.CacheHelper;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;


/**
 * Created by Administrator on 2016/8/11.
 */

public enum ServiceFactory {
    INSTANCE;

    APIService apiService;

    ServiceFactory() {
        apiService = RetrofitClient.getInstance().create(APIService.class);
    }

    public Observable<UserBean> postStart(String url, Map<String, Object> map) {
        String[] path = url.split("/");
        if (map == null)
            map = new HashMap<String, Object>();
        return apiService.postStart(path[0], path.length == 2 ? path[1] : "", map).compose(ServiceFactory.<UserBean>handleResult());
    }

    public Observable<UserBean> getStart(String url, Map<String, Object> map) {
        String[] path = url.split("/");
        if (map == null)
            map = new HashMap<String, Object>();
        return apiService.getStart(path[0], path.length == 2 ? path[1] : "", map).compose(ServiceFactory.<UserBean>handleResult());
    }

    public Observable<List<PptBean>> getPpt(String url, Map<String, Object> map) {
        if (map == null)
            map = new HashMap<String, Object>();
        return apiService.getPpt(url, map).compose(ServiceFactory.<List<PptBean>>handleResult());
    }

    public Observable<List<NppBean>> getNpp(String url, Map<String, Object> map) {
        if (map == null)
            map = new HashMap<String, Object>();
        return apiService.getNpp(url, map).compose(ServiceFactory.<List<NppBean>>handleResult());
    }

    public Observable<List<String>> getFirstCategory() {
        return apiService.getFirstCategory().compose(ServiceFactory.<List<String>>handleResult());
    }

    //调用方法
//    Observable<LoginData> fromNetwork = Api.getDefault()
//            .login(phone, password)
//            .compose(RxHelper.handleResult());
//    RetrofitCache.load(context,cacheKey,100000L,fromNetwork,false)
//            .subscribe(new RxSubscribe<LoginData>(context, "登录中") {
//        @Override
//        protected void _onNext(LoginData data) {
//            showToast(R.string.login_success);
//            //TODO login success
//        }
//
//        @Override
//        protected void _onError(String message) {
//            showToast(message);
//        }
//    });


    /**
     * 对结果进行预处理
     *
     * @param <T>
     * @return
     */
    public static <T> Observable.Transformer<BaseBean<T>, T> handleResult() {
        return new Observable.Transformer<BaseBean<T>, T>() {
            @Override
            public Observable<T> call(Observable<BaseBean<T>> tObservable) {
                return tObservable.flatMap(new Func1<BaseBean<T>, Observable<T>>() {
                    @Override
                    public Observable<T> call(BaseBean<T> result) {
                        Logger.i("result from network : " + result);
                        if (result.getCode() == 1) {
                            return createData(result.getData());
                        } else {
                            Logger.d(result.getErrorInfo());
                            return Observable.error(new ServerException(result.getCode(), result.getErrorInfo()));
                        }
                    }
                }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
            }
        };

    }

    /**
     * 创建成功的数据
     *
     * @param data
     * @param <T>
     * @return
     */
    private static <T> Observable<T> createData(final T data) {
        return Observable.create(new Observable.OnSubscribe<T>() {
            @Override
            public void call(Subscriber<? super T> subscriber) {
                try {
                    subscriber.onNext(data);
                    subscriber.onCompleted();
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            }
        });

    }

    /**
     * 处理服务器返回数据的缓存问题
     *
     * @param cacheKey
     * @param expireTime
     * @param fromNetwork
     * @param forceRefresh
     * @param <T>
     * @return
     */
    public <T> Observable<T> load(final String cacheKey,
                                  final int expireTime,
                                  Observable<T> fromNetwork,
                                  boolean forceRefresh) {
        Observable<T> fromCache = Observable.create(new Observable.OnSubscribe<T>() {
            @Override
            public void call(Subscriber<? super T> subscriber) {
                T cache = (T) CacheHelper.getAsObject(cacheKey);
                if (cache != null) {
                    subscriber.onNext(cache);
                } else {
                    subscriber.onCompleted();
                }
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());


        /**
         * 这里的fromNetwork 不需要指定Schedule,在handleRequest中已经变换了
         */
        fromNetwork = fromNetwork.map(new Func1<T, T>() {
            @Override
            public T call(T result) {
                CacheHelper.put(cacheKey, (Serializable) result, expireTime);
                return result;
            }
        });
        if (forceRefresh) {
            return fromNetwork;
        } else {
            return Observable.concat(fromCache, fromNetwork).first();
        }
    }

    /**
     * 处理服务器返回数据的缓存问题
     *
     * @param cacheKey
     * @param fromNetwork
     * @param forceRefresh
     * @param <T>
     * @return
     */
    public <T> Observable<T> load(final String cacheKey,
                                  Observable<T> fromNetwork,
                                  boolean forceRefresh) {
        Observable<T> fromCache = Observable.create(new Observable.OnSubscribe<T>() {
            @Override
            public void call(Subscriber<? super T> subscriber) {
                T cache = (T) CacheHelper.getAsObject(cacheKey);
                if (cache != null) {
                    subscriber.onNext(cache);
                } else {
                    subscriber.onCompleted();
                }
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());


        /**
         * 这里的fromNetwork 不需要指定Schedule,在handleRequest中已经变换了
         */
        fromNetwork = fromNetwork.map(new Func1<T, T>() {
            @Override
            public T call(T result) {
                CacheHelper.put(cacheKey, (Serializable) result);
                return result;
            }
        });
        if (forceRefresh) {
            return fromNetwork;
        } else {
            return Observable.concat(fromCache, fromNetwork).first();
        }
    }
}
